﻿using System;
using System.Collections.Generic;
using System.Text;

using Log;
using System.Data.SQLite;
using System.IO;

namespace ilibrary.source.model
{
    /// <summary>
    /// Classe représentant la collection d'ebooks. Elle offre des méthodes permettant le chargement des ebooks au démarrage
    /// , le scan des dossiers à la recherche d'ebooks...
    /// </summary>
    public class Library
    {
        private static EventLog log = new EventLog("ILibrary", "Library");
        private Dictionary<int, IEbook> ebooksView = new Dictionary<int, IEbook>();

        #region Singleton
        private static Library library = new Library();

        public static Library Instance
        {
            get
            {
                return library;
            }
        }

        protected Library() { }
        #endregion

        /// <summary>
        /// Scanne les dossiers de la collections à la recherche d'ebooks
        /// </summary>
        public void ScanFolders(string folderPath, ScanHandler cb)
        {
            try
            {
                List<string> folders = new List<string>();
                if (folderPath == null)
                {
                    folders.AddRange(SqlliteDB.Instance.getAllFolders());
                }
                else folders.Add(folderPath);


                List<string> files = new List<string>();
                int total = 0;
                foreach (String s in folders)
                {
                    foreach (string pat in EbookHandlerFactory.Instance.GetAllSupportedFormats())
                    {
                        string pattern = "*" + pat;
                        string[] tmp = System.IO.Directory.GetFiles(s, pattern, SearchOption.AllDirectories);
                        total += tmp.GetLength(0);
                        files.AddRange(tmp);
                    }
                }

                int count = 0;

                foreach (string ebook in files)
                {
                    try
                    {
                        //pour chaque fichier, on vérifie s'il y a un handler qui le supporte.
                        //si c'est le cas on l'ajoute à la collection (s'il n'y figure pas déjà)
                        string ext = System.IO.Path.GetExtension(ebook);
                        if (ext != null)
                        {
                            ext = ext.ToLower();
                            IEbookHandler handler = Program.HandlerFactory.GetHandler(ext);
                            if (handler != null)
                            {
                                if (!SqlliteDB.Instance.ebookExists(ebook))
                                {
                                    SqlliteDB.Instance.insertEbook(ebook);
                                }
                            }
                        }

                        //callback
                        count++;
                        if (cb != null && cb.ebookAdded((float)(count * 100.0 / total), ebook) == false)
                        {
                            //cancel
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Warn(string.Concat("The ebook ", ebook, " hasn't been loaded"), ex);
                    }
                }

            }
            catch (Exception ex)
            {
                log.Error("", ex);
            }
        }

        /// <summary>
        /// Charge la liste de tous les ebooks de la base
        /// </summary>
        public Dictionary<int, IEbook> LoadAllEbooks()
        {
            try
            {
                ebooksView.Clear();

                SqlliteDB.Instance.loadAllEbooks(ebooksView);

                return ebooksView;
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        public Dictionary<int, IEbook> LoadFavouritesEbooks()
        {
            try
            {
                ebooksView.Clear();

                SqlliteDB.Instance.loadFavouritesEbooks(ebooksView);

                return ebooksView;
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        public Dictionary<int, IEbook> LoadEbooksWithTags(List<int> tags)
        {
            try
            {
                ebooksView.Clear();

                SqlliteDB.Instance.loadEbooksWithTags(ebooksView, tags);

                return ebooksView;
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        public Dictionary<int, IEbook> LoadEbooksType(string type)
        {
            try
            {
                ebooksView.Clear();

                SqlliteDB.Instance.loadEbooksType(ebooksView, type);

                return ebooksView;
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        /// <summary>
        /// Retourne la liste de tous les dossiers 
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllFolders()
        {
            return SqlliteDB.Instance.getAllFolders();
        }

        /// <summary>
        /// Ajoute un nouveau dossier a scanner
        /// </summary>
        /// <param name="path"></param>
        public void AddFolder(string path)
        {
            SqlliteDB.Instance.insertNewFolder(path);
        }


        /// <summary>
        /// Supprime l'un des dossiers existant
        /// </summary>
        /// <param name="path"></param>
        public void RemoveFolder(string path)
        {
            SqlliteDB.Instance.deleteFolder(path);
        }


        public bool RemoveEbook(int id)
        {
            SqlliteDB.Instance.deleteEbook(id);
            return true;
        }

        public IEbook GetEbookFromId(int id)
        {
            return SqlliteDB.Instance.GetEbook(id);
        }

        public void ClearEbookMetadata(int id)
        {
            IEbook ebook = SqlliteDB.Instance.GetEbook(id);
            if (ebook != null)
            {
                ebook.Authors = null;
                ebook.Description = null;
                ebook.ISBN = null;
                ebook.Publisher = null;
                ebook.Summary = null;
            }
        }

        public void ClearEbookCollection()
        {
            SqlliteDB.Instance.clearEbookCollection();
        }

        public int EbookCount()
        {
            return SqlliteDB.Instance.ebookCount();
        }


        public List<string> SelectAllTag()
        {
            return SqlliteDB.Instance.selectAllTag();
        }

        public Dictionary<int, string> SelectAllTagWithId()
        {
            return SqlliteDB.Instance.selectAllTagWithId();
        }

        public int SelectTagId(string tag)
        {
            return SqlliteDB.Instance.selectTagId(tag);
        }

        public void AddTag(string tagLabel)
        {
            SqlliteDB.Instance.insertTag(tagLabel);
        }

        public void UpdateTag(int tagId, string tagLabel)
        {
            SqlliteDB.Instance.updateTag(tagId, tagLabel);
        }

        public void DeleteTag(int tagId)
        {
            SqlliteDB.Instance.deleteTag(tagId);
        }


        public bool EbookHasTag(int ebookId, int tagId)
        {
            return SqlliteDB.Instance.ebookTagExist(ebookId, tagId);
        }

        public void AddTagToEbook(int ebookId, int tagId)
        {
            SqlliteDB.Instance.insertEbookTag(ebookId, tagId);
        }

        public void RemoveTagToEbook(int ebookId, int tagId)
        {
            SqlliteDB.Instance.deleteEbookTag(ebookId, tagId);
        }

        public List<string> SelectTagsForEBook(int ebookId)
        {
            return SqlliteDB.Instance.selectTagsForEBook(ebookId);
        }


        public void UpdatePersonalNotes(int ebookId, string chapterPath, string notes)
        {
            SqlliteDB.Instance.updatePersonalNotes(ebookId, chapterPath, notes);
        }

        public bool PersonalNotesExist(int ebookId, string chapterPath)
        {
            return SqlliteDB.Instance.notesExist(ebookId, chapterPath);
        }

        public string SelectPersonalNotes(int ebookId, string chapterPath)
        {
            return SqlliteDB.Instance.selectPersonalNotesNotes(ebookId, chapterPath);
        }

        public void AddPersonalNotes(int ebookId, string chapterPath, string notes)
        {
            SqlliteDB.Instance.insertPersonalNotes(ebookId, chapterPath, notes);
        }
    }
}
